home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / x11 / dfb.c next >
Encoding:
C/C++ Source or Header  |  1996-07-25  |  20.3 KB  |  807 lines

  1. #include <X11/Xlib.h> 
  2. #include <X11/Xutil.h>
  3. #include <X11/keysym.h>
  4.  
  5. #ifndef NO_XSHM
  6. #include <sys/ipc.h>
  7. #include <sys/shm.h>
  8. #include <X11/extensions/XShm.h>
  9. #include <signal.h>
  10. #endif
  11.  
  12. #include <string.h>
  13. #ifdef _AIX
  14. #include <strings.h>
  15. #endif
  16.  
  17. #include "filter.hpp"
  18. #include "globals.hpp"
  19. #include "system.h"
  20. #include "video.hpp"
  21. #include "dos.h"
  22. #include "xinclude.h"
  23. #include "macs.hpp"
  24. #include "bitmap.h"
  25. #include "image.hpp"
  26. #include "jmalloc.hpp"
  27.  
  28. unsigned char current_background;
  29. extern unsigned int xres,yres;
  30. extern palette *lastl;
  31. int X_xoff,Y_yoff,vmode;
  32. image *screen;
  33. char display_name[120];
  34.  
  35. Window root;
  36. Display *display;
  37. int screen_num;
  38. Screen *screen_ptr;
  39. unsigned border_width,depth;
  40. Colormap XCMap;
  41. Window mainwin;
  42. GC gc;
  43. XFontStruct *font_info;
  44. XVisualInfo *my_visual;
  45. Visual *X_visual;
  46.  
  47. static int pixel_scale=1;
  48.  
  49. uchar last_load_palette[256*4];  // store word alligned for faster access
  50.  
  51.  
  52.  
  53.  
  54. // ========================================================================
  55. // makes a null cursor
  56. // ========================================================================
  57.  
  58. static Cursor CreateNullCursor(Display *display, Window root)
  59. {
  60.     Pixmap cursormask; 
  61.     XGCValues xgc;
  62.     GC gc;
  63.     XColor dummycolour;
  64.     Cursor cursor;
  65.  
  66.     cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
  67.     xgc.function = GXclear;
  68.     gc =  XCreateGC(display, cursormask, GCFunction, &xgc);
  69.     XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
  70.     dummycolour.pixel = 0;
  71.     dummycolour.red = 0;
  72.     dummycolour.flags = 04;
  73.     cursor = XCreatePixmapCursor(display, cursormask, cursormask,
  74.           &dummycolour,&dummycolour, 0,0);
  75.     XFreePixmap(display,cursormask);
  76.     XFreeGC(display,gc);
  77.     return cursor;
  78. }
  79.  
  80.  
  81.  
  82. #ifndef NO_XSHM
  83. // ************** SHM Vars *******************
  84. int shm_base,shm_error_base,shm_finish_event,doShm=0;
  85.  
  86.  
  87. struct event_node
  88. {
  89.   XEvent report;  
  90.   event_node *next;  
  91. } ;
  92.  
  93.  
  94. void wait_shm_finish()
  95. {
  96.   event_node *en,*first=NULL;
  97.   while (1)
  98.   { 
  99.     en=(event_node *)jmalloc(sizeof(event_node),"shm_wait : event");
  100.     XNextEvent(display, &en->report);
  101.  
  102.     // if this is the finishing event, put all the stored events back
  103.     // on the que
  104. #ifndef NO_XSHM
  105.     if (en->report.type==shm_base+ShmCompletion)
  106.     {
  107.       jfree(en);
  108.       
  109.       while (first)
  110.       {
  111.     XPutBackEvent(display,&first->report);
  112.     en=first;
  113.     first=first->next;
  114.     jfree(en);    
  115.       }
  116.       return ;      
  117.     } else // put the event on the que to be puback
  118. #endif
  119.     {
  120.       en->next=first;     // put the back in reverse order
  121.       first=en;
  122.     }    
  123.   }
  124. }
  125.  
  126.     
  127. #endif
  128.  
  129.  
  130. int get_vmode()
  131. { return vmode; }
  132.  
  133. void getGC(Window win, GC *gc, XFontStruct *font_info)
  134. {
  135.   XGCValues values;
  136.   *gc=XCreateGC(display,win,0,&values);
  137.   XSetFont(display, *gc, font_info->fid);
  138.   XSetForeground(display, *gc, BlackPixel(display,screen_num));
  139.   XSetLineAttributes(display, *gc, 1, LineSolid, CapRound, JoinRound);
  140. }
  141.  
  142.  
  143. class XImage_Info             // stored in the extended desciptor
  144. {
  145. public :
  146.   
  147. #ifndef NO_XSHM
  148.   XShmSegmentInfo X_shminfo;    
  149. #endif
  150.   XImage *XImg;
  151. } ;
  152.  
  153.  
  154. void image::make_page(short width, short height, unsigned char *page_buffer)
  155. {
  156.   XImage_Info *xi;  
  157.   if (special && !special->static_mem)
  158.   {
  159.     xi=new XImage_Info;
  160.     special->extended_descriptor=(void *)xi;    
  161. #ifndef NO_XSHM
  162.     if (doShm)
  163.     {
  164.       width=(width+3)&(0xffffffff-3);
  165.       // create the image
  166.       xi->XImg = XShmCreateImage(display,
  167.                  X_visual,
  168.                  my_visual->depth,
  169.                  ZPixmap,
  170.                  0,
  171.                  &xi->X_shminfo,
  172.                  width*pixel_scale,
  173.                  height*pixel_scale);
  174.  
  175.       w = width = xi->XImg->bytes_per_line / pixel_scale;
  176.  
  177.       // create the shared memory segment
  178.       xi->X_shminfo.shmid = shmget (IPC_PRIVATE,
  179.           width*height*pixel_scale*pixel_scale, IPC_CREAT | 0777);
  180.       ERROR(xi->X_shminfo.shmid>=0,"shmget() failed, go figure");
  181.  
  182.       xi->X_shminfo.readOnly=False;
  183.  
  184.       // attach to the shared memory segment to us
  185.       xi->XImg->data = xi->X_shminfo.shmaddr =
  186.         (char *) shmat(xi->X_shminfo.shmid, 0, 0);
  187.       ERROR(xi->XImg->data,"shmat() failed, go figure");
  188.  
  189.       // get the X server to attach to it to the X server
  190.       ERROR(XShmAttach(display, &xi->X_shminfo),"XShmAttach() failed, go figure");
  191.       XSync(display,False); // make sure segment gets attached
  192.       ERROR(shmctl(xi->X_shminfo.shmid,IPC_RMID,NULL)==0,"shmctl failed, why?"); 
  193.  
  194.       if (pixel_scale == 1)
  195.         data=(unsigned char *) (xi->XImg->data);
  196.       else
  197.         data=(unsigned char *) jmalloc(width*height, "unscaled image");
  198.     } else 
  199. #endif
  200.     {
  201.       width=(width+3)&(0xffffffff-3);        
  202.       if (!page_buffer)
  203.         page_buffer=
  204.             (unsigned char *)jmalloc(width*height*pixel_scale*pixel_scale,
  205.             "image::data");
  206.       
  207.       xi->XImg = XCreateImage(    display,
  208.                     X_visual,
  209.                     my_visual->depth,
  210.                     ZPixmap,
  211.                     0,
  212.                     (char *)page_buffer,
  213.                     width*pixel_scale,
  214.                     height*pixel_scale,
  215.                     32,
  216.                     0 );
  217.       ERROR(xi->XImg,"XCreateImage failed");
  218.  
  219.       w = width = xi->XImg->bytes_per_line / pixel_scale;
  220.  
  221.       if (pixel_scale == 1)
  222.           data=(unsigned char *) (xi->XImg->data);
  223.         else
  224.         data=(unsigned char *) jmalloc(width*height, "unscaled image");
  225.     }    
  226.   }
  227.   else 
  228.   {
  229.     if (!page_buffer)
  230.       data=(unsigned char *)jmalloc(width*height,"image::data");
  231.     else data=page_buffer;
  232.   }
  233.  
  234.   if (special)
  235.     special->resize(width,height);
  236.  
  237. }
  238.  
  239. void image::delete_page()
  240.   XImage_Info *xi;  
  241.   if (special && !special->static_mem && special->extended_descriptor)
  242.   {    
  243.     xi=(XImage_Info *)special->extended_descriptor;    
  244. #ifndef NO_XSHM
  245.     if (doShm)
  246.     {    
  247.       XFlush(display);
  248.       XSync(display,False);  // maker sure anything with this image is drawn!
  249.  
  250.       // Dettach the memory from the server
  251.       ERROR(XShmDetach(display, &xi->X_shminfo),"XShmDetach() failed, go figure");
  252.  
  253.       XSync(display,False);  // maker sure server detached
  254.  
  255.       // detach the memory from us, it will be deleted!
  256.       ERROR(shmdt(xi->X_shminfo.shmaddr)>=0,"shmdt failed, oops");
  257.  
  258.       xi->XImg->data=NULL;  // tell X not to try to free the memory, cause we already did.
  259.  
  260.       XDestroyImage(xi->XImg);    
  261.  
  262.       if (pixel_scale > 1)
  263.         jfree(data);
  264.  
  265.     } else
  266. #endif
  267.     {
  268.       if (!special->static_mem)
  269.         jfree(xi->XImg->data);
  270.       xi->XImg->data=NULL;                  // make sure X doesn't try to free static memory
  271.       XDestroyImage(xi->XImg);    
  272.  
  273.       if (pixel_scale > 1)
  274.         jfree(data);
  275.     }
  276.     delete xi;
  277.   }
  278.   else if (!special)
  279.     jfree(data);      
  280. }
  281.  
  282.  
  283. #ifndef NO_XSHM
  284. #ifdef __sgi
  285. void clean_shm(...)
  286. #else
  287. void clean_shm(int why)      // on exit, delete all images, so shm get de-allocated.
  288. #endif
  289. {
  290.   while (image_list.first())
  291.   {
  292.     image *i=(image *)image_list.first();
  293.     delete i;
  294.   }
  295. }
  296. #endif
  297.  
  298. void set_mode(int mode, int argc, char **argv)
  299. {
  300.   unsigned char *page;
  301.   vmode=mode;
  302.   XVisualInfo vis_info;
  303.   int items,i;
  304.   XEvent report;
  305.   XWMHints *wm_hints;
  306.   XClassHint *class_hints;
  307.   XTextProperty winName,iconName;
  308.   XSizeHints *size_hints;
  309.   char *win_name=argv[0],        // name the window and the icon the executable name
  310.        *icon_name=argv[0];
  311.   Pixmap icon_pixmap;
  312.   
  313.   // get the default display name from the enviroment variable DISPLAY
  314.   char *ds_name=getenv("DISPLAY");
  315.   if (!ds_name) ds_name="unix:0.0";
  316.   strcpy(display_name,ds_name); 
  317.  
  318.   int suppress_shm=0;
  319.  
  320.   // check for command line display name
  321.   for (i=1;i<argc;i++)
  322.   {
  323.     if (!strcasecmp(argv[i],"-display") || !strcasecmp(argv[i],"-disp"))
  324.     {
  325.       i++;      
  326.       strcpy(display_name,argv[i]);  
  327.     }    
  328.     else if (!strcasecmp(argv[i],"-noshm"))
  329.       suppress_shm=1;
  330.     else if (!strcasecmp(argv[i],"-pixel_scale"))
  331.       pixel_scale=atoi(argv[i+1]);
  332.   }
  333.     
  334.   display=XOpenDisplay(display_name);  
  335.   if (!display)
  336.   {
  337.     printf("Cound not connect to X server named '%s'\n",display_name);
  338.     exit(1);
  339.   }
  340.  
  341. #ifndef NO_XSHM
  342.   // check for the MITSHM extension
  343.   int major_op;
  344.   
  345.   if (suppress_shm)
  346.     doShm=0;
  347.   else
  348.     doShm = XQueryExtension(display,"MIT-SHM",&major_op,&shm_base,&shm_error_base);
  349.  
  350.   // make sure it's a local connection
  351.   if (doShm)
  352.   {    
  353.     char *d = display_name;
  354.     while (*d && (*d != ':')) d++;
  355.     if (*d) *d = 0;
  356.     if (strcasecmp(display_name, "unix") && display_name[0]!=0) 
  357.       doShm = 0;   
  358.   }
  359.  
  360.   if (doShm)
  361.   {
  362.     printf("Using MITSHM extension!\n");
  363.     int sigs[29]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,
  364.         SIGABRT,SIGIOT,SIGBUS,SIGFPE,SIGKILL,
  365.         SIGUSR1,SIGSEGV,SIGUSR2,SIGPIPE,SIGALRM,
  366.                 SIGTERM,SIGCHLD,SIGCONT,SIGSTOP,
  367.         SIGTSTP,SIGTTIN,SIGTTOU,SIGIO,
  368.         SIGURG,SIGXCPU,SIGXFSZ,SIGVTALRM,SIGPROF,
  369.         SIGWINCH};
  370.  
  371.     for (int i=0;i<29;i++)
  372.       signal(sigs[i],clean_shm);
  373.   }
  374. #endif
  375.   depth=8;
  376.   screen_num = DefaultScreen(display);
  377.   screen_ptr = DefaultScreenOfDisplay(display);
  378.   ERROR(XGetGeometry(display,RootWindow(display,screen_num), &root,
  379.     &X_xoff,&Y_yoff,&xres,&yres,&border_width,&depth),
  380.     "can't get root window attributes");
  381.  
  382.   {
  383.     vis_info.c_class=PseudoColor;       
  384.     vis_info.depth=8;
  385.     my_visual=XGetVisualInfo(display,VisualClassMask | VisualDepthMask, &vis_info,&items);
  386.     X_visual=my_visual->visual;
  387.  
  388.     if (items>0)
  389.     {
  390.       int rc;
  391.  
  392.       vmode=XWINDOWS_256;
  393.  
  394.       rc=XMatchVisualInfo(display, screen_num, 8, PseudoColor, &vis_info);
  395.       ERROR(rc, "What the hell? Non-8 bit Psuedo color..\n");
  396.       X_visual = my_visual->visual = vis_info.visual;
  397.       //    ERROR(my_visual->depth==8,"What the hell? Non-8 bit Psuedo color..\n");
  398.       printf("Using 8 bit Psuedo color\n");
  399.     }
  400.     else
  401.     { 
  402.       printf("X windows screen type not supported\n");
  403.       exit(0); 
  404.     }
  405.   }
  406.  
  407.   xres=320; yres=200;
  408.   for (i=1;i<argc;i++)
  409.   { if (!strcmp(argv[i],"-size"))
  410.     { i++; if (!sscanf(argv[i],"%d",&xres)) xres=320;
  411.       i++; if (!sscanf(argv[i],"%d",&yres)) yres=200;
  412.     }
  413.   }
  414.  
  415.  
  416.   Colormap tmpcmap;
  417.   
  418.   tmpcmap = XCreateColormap(display, XRootWindow(display,
  419.                         my_visual->screen), X_visual, AllocNone);
  420.  
  421.   int attribmask = CWColormap | CWBorderPixel;
  422.   XSetWindowAttributes attribs;
  423.   attribs.border_pixel = 0;
  424.   attribs.colormap = tmpcmap;
  425.   
  426.   mainwin=XCreateWindow(display,
  427.             XRootWindow(display,my_visual->screen),
  428.             0,0,xres*pixel_scale, yres*pixel_scale,
  429.             0,
  430.             my_visual->depth,
  431.             InputOutput,
  432.             X_visual,
  433.             attribmask,
  434.             &attribs);
  435.   xres--; yres--;
  436.  
  437.  
  438.   icon_pixmap=XCreateBitmapFromData(display,mainwin,bitmap_bits,
  439.     bitmap_width, bitmap_height);
  440.   ERROR((size_hints=XAllocSizeHints()),"memory allocation error");
  441.   ERROR((wm_hints=XAllocWMHints()),"memory allocation error");
  442.   ERROR((class_hints=XAllocClassHint()),"memory allocation error");
  443.  
  444.   int lock=0;
  445.   for (i=1;i<argc;i++)
  446.     if (!strcmp(argv[i],"-lock_size"))
  447.      lock=1;
  448.  
  449.   if (lock)
  450.   {
  451.     size_hints->flags=PPosition | PSize | PMinSize | PMaxSize;
  452.     size_hints->min_width  = (xres+1)*pixel_scale;
  453.     size_hints->min_height = (yres+1)*pixel_scale;
  454.     size_hints->max_width  = (xres+1)*pixel_scale;
  455.     size_hints->max_height = (yres+1)*pixel_scale;
  456.   }
  457.   else
  458.   {
  459.     size_hints->flags=PPosition | PSize | PMinSize;
  460.     size_hints->min_width  = 320;
  461.     size_hints->min_height = 200;
  462.   }
  463.  
  464.  
  465.   ERROR(XStringListToTextProperty(&win_name,1,&winName),"alloc failed");
  466.   ERROR(XStringListToTextProperty(&icon_name,1,&iconName),"alloc fialed");
  467.   wm_hints->initial_state=NormalState;  // not iconified at first
  468.   wm_hints->input=1;                  // needs keyboard input
  469.   wm_hints->icon_pixmap=icon_pixmap;
  470.   wm_hints->flags=StateHint | IconPixmapHint | InputHint;
  471.   class_hints->res_name=argv[0];
  472.   class_hints->res_class="(C) 1995 Crack dot Com, Jonathan Clark";
  473.   XSetWMProperties(display,mainwin,&winName,&iconName,argv,argc,size_hints,
  474.     wm_hints,class_hints);
  475.   XSelectInput(display,mainwin,ExposureMask|KeyPressMask|ButtonPressMask|
  476.     StructureNotifyMask);
  477.   ERROR(font_info=XLoadQueryFont(display,"9x15"),"cannot open 9x15");
  478.   getGC(mainwin,&gc,font_info);
  479.  
  480. /* try to determine what type of monitor we are using */
  481.  
  482.  
  483.   // detect which type of screen the X client will run on...
  484.   // if they requested 24 bit mode, check for that type of display
  485.  
  486.  
  487.  
  488.   XSetBackground(display,gc,BlackPixel(display,screen_num));
  489.  
  490.   XMapWindow(display,mainwin);
  491.   do
  492.   { XNextEvent(display, &report);
  493.   } while (report.type!= Expose);     // wait for our window to pop up
  494.  
  495.  
  496.   XDefineCursor(display,mainwin, CreateNullCursor(display,mainwin));
  497.  
  498.   screen=new image(xres+1,yres+1,NULL,2);  
  499.  
  500.   XCMap=XCreateColormap(display,mainwin,X_visual,AllocAll);  
  501.   screen->clear();
  502.   update_dirty(screen);
  503.  
  504.   for (i=1;i<argc;i++)
  505.   { if (!strcmp(argv[i],"-grab_pointer"))
  506.     {
  507.       i++;
  508.       int sec;
  509.       if (i<argc && sscanf(argv[i],"%d",&sec))
  510.       { printf("-grab_pointer : delaying for %d seconds\n",sec);
  511.     sleep(sec);
  512.       }
  513.       if (XGrabPointer(display,mainwin,True,
  514.                PointerMotionMask|ButtonMotionMask|
  515.                Button1MotionMask|
  516.                Button2MotionMask|
  517.                Button3MotionMask|
  518.                Button4MotionMask|
  519.                Button5MotionMask,
  520.                GrabModeAsync,
  521.                GrabModeAsync,
  522.                mainwin,
  523.                None,
  524.                CurrentTime)==GrabSuccess)
  525.         printf("Pointer grab in effect!\n");
  526.       else
  527.         printf("Unable to grab pointer  :(\n");
  528.     }
  529.   }
  530.     
  531. }
  532.  
  533. void close_graphics()
  534. {
  535.   if (lastl) delete lastl; lastl=NULL;
  536.   delete screen;
  537.   XUnloadFont(display,font_info->fid);
  538.   XFreeGC(display,gc);
  539.   XFree((char *)my_visual);
  540.   XCloseDisplay(display);
  541. }
  542.  
  543. void scale_image(image *im, int src_x, int src_y, int src_w, int src_h)
  544. {
  545.  
  546.   uchar *src;
  547.   ushort *dst;
  548.   ushort pixel;
  549.   int dx;
  550.   int y;
  551.   int next_dst_line;
  552.   int w;
  553.   XImage_Info *xi=(XImage_Info *)im->special->extended_descriptor;
  554.  
  555.   if (pixel_scale == 2)
  556.   {
  557.       src=im->scan_line(src_y)+src_x;
  558.       dst=(ushort *) (xi->XImg->data+src_y*xi->XImg->bytes_per_line*2+src_x*2);
  559.       next_dst_line = xi->XImg->bytes_per_line/2;
  560.       w = im->width();
  561.  
  562.       for (y=src_h;y;y--)
  563.       {
  564.         for (dx=0;dx<src_w;dx++)
  565.         {
  566.           pixel = *(src+dx);
  567.           pixel |= pixel<<8;
  568.           *(dst+dx) = pixel;
  569.           *(dst+dx+next_dst_line) = pixel;
  570.         }
  571.         src += w;
  572.         dst += xi->XImg->bytes_per_line;
  573.       }
  574.  
  575.   }
  576.  
  577. }
  578.  
  579. void copy_24part(uchar *Xdata, image *im, int x1, int y1, int x2, int y2)
  580. {
  581.   uchar *src=im->scan_line(y1)+x1;
  582.   ushort *dst=(ushort *)Xdata+(y1*2)*im->width()+x1;
  583.  
  584.   int src_add=im->width()-(x2-x1+1);
  585.  
  586.   int x,y,w=(x2-x1+1)*2;
  587.   ushort v;
  588.   for (y=y1;y<=y2;y++)
  589.   {
  590.     for (x=x1;x<=x2;x++)
  591.     {
  592.       v=*(src++);
  593.       *(dst++)=(v|(v<<8));
  594.     }    
  595.     dst=(ushort *) ((uchar *)dst+src_add*2);
  596.     memcpy(dst,(uchar *)dst-im->width()*2,w);
  597.     dst=(ushort *)((uchar *)dst+im->width()*2);
  598.  
  599.     src+=src_add;
  600.   }
  601. }
  602.  
  603.  
  604.  
  605. void put_part_image(Window win, image *im, int x, int y, int x1, int y1, int x2, int y2)
  606. {
  607.   CHECK(im->special);
  608.   XImage_Info *xi=(XImage_Info *)im->special->extended_descriptor;
  609.  
  610.   if (pixel_scale>1)
  611.     scale_image(im,x1,y1,x2-x1+1,y2-y1+1);
  612.  
  613. #ifndef NO_XSHM
  614.   if (doShm)
  615.   {    
  616.     XEvent ev;
  617.     XSync(display,False);
  618.     if (XCheckTypedEvent(display, ConfigureNotify,&ev)==False)
  619.     {
  620.       XShmPutImage(display,win,gc,xi->XImg,x1*pixel_scale,y1*pixel_scale,
  621.         x*pixel_scale,y*pixel_scale,(x2-x1+1)*pixel_scale,
  622.         (y2-y1+1)*pixel_scale,True);
  623.       // wait for the Put to finish
  624.       wait_shm_finish();
  625.     } else     // screen size changed,  better wait till this event is handled cause put might be invalid
  626.       XPutBackEvent(display,&ev);
  627.  
  628.   }  
  629.   else  
  630. #endif
  631.     XPutImage(display,win,gc,xi->XImg,x1*pixel_scale,y1*pixel_scale,
  632.       x*pixel_scale,y*pixel_scale,(x2-x1+1)*pixel_scale,(y2-y1+1)*pixel_scale);
  633.  
  634. }
  635.  
  636. void put_image(image *im, int x, int y)
  637. {
  638.   put_part_image(mainwin,im,x,y,0,0,im->width()-1,im->height()-1);  
  639. }
  640.  
  641.  
  642.  
  643. void update_dirty_window(Window win, image *im, int xoff, int yoff)
  644. {
  645.  
  646.   int count;
  647.   dirty_rect *dr,*q;
  648.   image *Xim;
  649.   CHECK(im->special);  // make sure the image has the ablity to contain dirty areas
  650.   if (im->special->keep_dirt==0)
  651.     put_image(im,xoff,yoff);
  652.   else
  653.   {
  654.     count=im->special->dirties.number_nodes();
  655.     if (!count) return;  // if nothing to update, return
  656.     dr= (dirty_rect *) (im->special->dirties.first());
  657.     while (count>0)
  658.     {
  659.       put_part_image(win,im,xoff+dr->dx1,yoff+dr->dy1,dr->dx1,dr->dy1,dr->dx2,dr->dy2);     
  660. //      XDrawRectangle(display,mainwin,gc,xoff+dr->dx1,yoff+dr->dy1,
  661. //             xoff+dr->dx2-dr->dx1+1,yoff+dr->dy2-dr->dy1+1);
  662.       q=dr;
  663.       dr=(dirty_rect *) (dr->next());
  664.       im->special->dirties.unlink((linked_node *)q);
  665.       delete q;
  666.       count--;
  667.     }
  668.   }
  669. //  XFlush(display);
  670. }
  671.  
  672. void update_dirty(image *im, int xoff, int yoff)
  673. { update_dirty_window(mainwin,im,xoff,yoff); }
  674.  
  675. void palette::load()
  676. {
  677.   if (lastl)
  678.     delete lastl;
  679.   lastl=copy();
  680.  
  681.   {
  682.     int i;
  683.     if (get_vmode()!=XWINDOWS_2)
  684.     {
  685.       XColor color;
  686.       color.flags=DoRed|DoBlue|DoGreen;
  687.       for (i=0;i<ncolors;i++)
  688.       {
  689.     color.pixel=i;
  690.     color.red=red(i)<<8|0xff; color.green=green(i)<<8|0xff; color.blue=blue(i)<<8|0xff;
  691.     XStoreColor(display,XCMap,&color);
  692.       }
  693.       XSetWindowColormap(display,mainwin,XCMap);
  694.     }
  695.     else lastl->black_white();
  696.     current_background=bg;
  697.   }
  698. }
  699.  
  700. struct hist_entry
  701. {
  702.   long total;
  703.   unsigned char org;
  704. } ;
  705.  
  706. static int histcompare(const void *i, const void *j)
  707.   if (((hist_entry *)i)->org==0) return -1;  // make sure the background gets allocated
  708.   else return(((hist_entry *)j)->total - ((hist_entry *)i)->total); 
  709. }
  710.  
  711.  
  712. void palette::load_nice()
  713. {
  714.   int i,fail,y,x,wd,j;
  715.   long closest_val,closest_pixel,k;
  716.   char *gotten;
  717.   image *im;
  718.   unsigned char *sl;
  719.   palette *Xpal;
  720.   hist_entry *histogram;
  721.   Colormap stdcm;
  722.   XColor color;
  723.  
  724.   if (get_vmode()!=XWINDOWS_2)  
  725.   {
  726.     filter f(ncolors);
  727.  
  728.     histogram=(hist_entry *)jmalloc(sizeof(hist_entry)*ncolors,"palette::histogram"); 
  729.     gotten=(char *)jmalloc(ncolors,"palette::gotten_colors");
  730.  
  731.     memset(gotten,0,ncolors);
  732.     for (i=0;i<ncolors;i++)
  733.     { histogram[i].total=0;
  734.       histogram[i].org=i;
  735.     }
  736.  
  737.     for (i=image_list.number_nodes(),im=(image *)image_list.first();i;i--,im=(image *)im->next()) 
  738.     { 
  739.       if (im!=screen)
  740.       { 
  741.         wd=im->width();
  742.         for (y=im->height();y;y--)
  743.         {
  744.           sl=im->scan_line(y-1);
  745.           for (x=0;x<wd;x++)
  746.             histogram[sl[x]].total++;
  747.         }
  748.       }
  749.     }
  750.     qsort(histogram,ncolors,sizeof(hist_entry),histcompare);
  751.     stdcm=XDefaultColormap(display,screen_num);
  752.     Xpal=NULL;
  753.     for (i=0,fail=0;i<ncolors;i++)
  754.     {
  755.       color.red=red(histogram[i].org)<<8; 
  756.       color.green=green(histogram[i].org)<<8; 
  757.       color.blue=blue(histogram[i].org)<<8; 
  758.  
  759.       if (XAllocColor(display,stdcm,&color))
  760.         f.set(histogram[i].org,color.pixel);
  761.       else  // if we couldn't allocate that color from X, find the closest.
  762.       {
  763.         if (!Xpal)
  764.         { Xpal=new palette(ncolors);
  765.           for (j=0;j<ncolors;j++)
  766.           {
  767.             color.pixel=j;
  768.             XQueryColor(display,stdcm,&color);
  769.             Xpal->set(j,color.red>>8,color.green>>8,color.blue>>8);
  770.           }
  771.         }
  772.         closest_val=0xfffffff;
  773.         for (j=0;j<ncolors;j++)
  774.         {
  775.           k=Xpal->red(j)*Xpal->red(j)+Xpal->green(j)*Xpal->green(j)+
  776.             Xpal->blue(j)*Xpal->blue(j);
  777.           if (k<closest_val)
  778.           { closest_val=k;
  779.             closest_pixel=j;
  780.           }
  781.         }
  782.         f.set(histogram[i].org,closest_pixel);
  783.       }
  784.     }
  785.     if (!Xpal)
  786.       Xpal=new palette(ncolors);
  787.     // store the color mapping we created back to the palette.
  788.     for (j=0;j<ncolors;j++)
  789.       Xpal->set(j,red(f.get_mapping(j)),green(f.get_mapping(j)),blue(f.get_mapping(j)));
  790.     for (j=0;j<ncolors;j++)
  791.       set(j,Xpal->red(j),Xpal->green(j),Xpal->blue(j));  
  792.     bg=f.get_mapping(bg);
  793.       
  794.     // now remap all the images to fit this colormap!
  795.     for (i=image_list.number_nodes(),im=(image *)image_list.first();i;i--,im=(image *)im->next()) 
  796.       f.apply(im);
  797.  
  798.     delete Xpal;
  799.     jfree(histogram);
  800.     jfree(gotten);
  801.   }
  802.   current_background=bg;
  803. }
  804.  
  805.